package com.mocha.auth.component;

import cn.hutool.core.map.MapUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mocha.auth.util.SpringContextHolder;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.core.convert.converter.Converter;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.GenericHttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.security.oauth2.core.endpoint.DefaultOAuth2AccessTokenResponseMapConverter;
import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;
import org.springframework.security.oauth2.core.http.converter.OAuth2AccessTokenResponseHttpMessageConverter;

import java.util.Map;
import java.util.Optional;

/**
 * 扩展原生的实现，支持 Long2String
 *
 * @author songkui
 * @since 2025-4-17
 */
public class CoffeeOAuth2AccessTokenResponseHttpMessageConverter extends OAuth2AccessTokenResponseHttpMessageConverter {

	private static final ParameterizedTypeReference<Map<String, Object>> STRING_OBJECT_MAP = new ParameterizedTypeReference<Map<String, Object>>() {
	};

	private final Converter<OAuth2AccessTokenResponse, Map<String, Object>> accessTokenResponseParametersConverter = new DefaultOAuth2AccessTokenResponseMapConverter();

	@Override
	protected void writeInternal(OAuth2AccessTokenResponse tokenResponse, HttpOutputMessage outputMessage)throws HttpMessageNotWritableException {
		try {
			Map<String, Object> tokenResponseParameters = this.accessTokenResponseParametersConverter.convert(tokenResponse);
            assert tokenResponseParameters != null;
            Map<String, Object> authInfo = buildAuthInfo(tokenResponseParameters);
			ObjectMapper objectMapper = SpringContextHolder.getBean(ObjectMapper.class);
			GenericHttpMessageConverter<Object> jsonMessageConverter = new MappingJackson2HttpMessageConverter(objectMapper);
            jsonMessageConverter.write(authInfo, STRING_OBJECT_MAP.getType(), MediaType.APPLICATION_JSON, outputMessage);
		}
		catch (Exception ex) {
			throw new HttpMessageNotWritableException(
					"An error occurred writing the OAuth 2.0 Access Token Response: " + ex.getMessage(), ex);
		}
	}

	private Map<String, Object> buildAuthInfo(Map<String, Object> params){

		if (params.get("user_id") == null){
			return params;
		}
		Map<String, Object> map = MapUtil.newHashMap(7);
		map.put("token_type", params.get("token_type"));
		map.put("access_token", params.get("access_token"));
		map.put("refresh_token", params.get("refresh_token"));
		map.put("expires_in", params.get("expires_in"));
		Optional.ofNullable(params.get("user_id")).ifPresent(o-> map.put("user_id", o.toString()));
		Optional.ofNullable(params.get("username")).ifPresent(o-> map.put("username", o.toString()));
		return map;

	}

}
